package com.wj.tool.common.bean.restful;

import com.wj.tool.common.exception.BusinessException;
import com.wj.tool.common.exception.message.InterfaceMessage;
import com.wj.tool.common.exception.message.SystemMessage;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Formatter;
import java.util.stream.Collectors;

/**
 * @description: 异常时处理类（系统出现自定义异常时 返回restfulbody）
 * @create: 2021/1/14 10:02
 */

@ControllerAdvice
public class GlobalWebExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalWebExceptionHandler.class);

    public GlobalWebExceptionHandler() {
    }

    @ExceptionHandler({MethodArgumentTypeMismatchException.class})
    @ResponseBody
    public RestfulResponseBody<Object> methodArgumentTypeError(MethodArgumentTypeMismatchException e) {
        String requestType = "";
        String message = "";
        String parameter = e.getParameter().getParameterName();
        int parameterIndex = e.getParameter().getParameterIndex();
        if (null != e.getRequiredType()) {
            requestType = e.getRequiredType().getTypeName();
        }

        Formatter formatter = new Formatter();
        Throwable var7 = null;

        try {
            formatter.format(" Parameter named '%s '(parameter index:%d), and the expected value type is %s ", parameter, parameterIndex, requestType);
            message = formatter.toString();
        } catch (Throwable var16) {
            var7 = var16;
            throw var16;
        } finally {
            if (formatter != null) {
                if (var7 != null) {
                    try {
                        formatter.close();
                    } catch (Throwable var15) {
                        var7.addSuppressed(var15);
                    }
                } else {
                    formatter.close();
                }
            }

        }

        if (logger.isErrorEnabled()) {
            logger.error("Method argument type error:", e);
        }

        return RestfulResponseUtils.errorResponse(InterfaceMessage.invalidParameter(message));
    }

    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseBody
    public RestfulResponseBody<Object> missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException e) {
        return RestfulResponseUtils.errorResponse(InterfaceMessage.invalidParameter(e.getMessage()));
    }

    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseBody
    public RestfulResponseBody<Object> constraintViolationExceptionHandler(ConstraintViolationException e) {
        String message = (String)e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return RestfulResponseUtils.errorResponse(InterfaceMessage.invalidParameter(message));
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public RestfulResponseBody<Object> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        String message = "";
        if (null != e.getBindingResult().getFieldError()) {
            message = e.getBindingResult().getFieldError().getDefaultMessage();
        }

        if (StringUtils.isEmpty(message)) {
            message = e.getBindingResult().getFieldError().getField();
        }

        return RestfulResponseUtils.errorResponse(InterfaceMessage.invalidParameter(message));
    }

    @ExceptionHandler({Exception.class})
    @ResponseBody
    public RestfulResponseBody<Object> unknownError(Exception e) {
        if (logger.isErrorEnabled()) {
            logger.error("An unknown exception has been generated : ", e);
        }

        return RestfulResponseUtils.errorResponse(SystemMessage.unknownError("unknown error"), new String[]{e.toString()});
    }

    @ExceptionHandler({BusinessException.class})
    @ResponseBody
    public RestfulResponseBody<Object> businessException(BusinessException e) {
        if (logger.isErrorEnabled()) {
            logger.error("An business exception has been generated : {}", e.getMessage());
        }

        return RestfulResponseUtils.errorResponse(e.getApplicationMessage());
    }
}